OPC Studio User's Guide and Reference
Dynamic User Identity Change
Concepts > QuickOPC Concepts > QuickOPC Features > Dynamic User Identity Change
In This Topic

Introduction

As explained in OPC UA User Authentication (Client), a connection (OPC UA session) can be associated with a specified user identity. In QuickOPC, the user identity is specified using the UserIdentity Property in the endpoint descriptor object (UAEndpointDescriptor Class) that is passed to QuickOPC operations. If you like, you can use different user identities, and QuickOPC will then create and maintain separate OPC UA sessions for them, one for every user identity.

In addition to the approach described above, OPC UA has a feature that allows the clients to change the identity of the user on an existing connection (OPC UA session), without having to close the session and re-open it. QuickOPC supports this feature as well. Note that this feature is only available if the OPC UA server also supports it.

Changing the user identity on an existing session has some performance advantages over creating a separate session for a new user identity. It also allows the client and the server to keep the existing data change and event subscriptions, without having to re-establish them, resulting in smoother transition.

The dynamic user identity change is sometimes called "user switching".

How It Works

The dynamic user identity change makes use of object alising. Basically, instead of using a specific constant user identity in the endpoint descriptor, you give it a name (an alias). The alias name remains the same, but the user identity value represented by the alias can be changed as you wish.

When QuickOPC detects that the user identity represented by the alias has changed, it picks up the new user identity. If there is an open OPC UA session associated with the endpoint descriptor, QuickOPC then attempts to switch the session to the new user identity.

If the user identity change succeeds (in the OPC UA server), the operations then proceed as normally, albeit with a new user identity, which means that the OPC UA session now possibly has different permissions. If the user identity change fails (for example, when the OPC UA server does not authenticate the newly required user), subsequent OPC UA operations using the same endpoint descriptor will return an error, and your subscriptions (event handlers or callbacks) will receive an error notification (and will stop receiving further notifications). You need to change the user identity back to the original identity, or to some other valid user identity, to resume the normal operations.

Procedure

In order to use the dynamic user identity change, your code typically needs to perform the following steps:

  1. Make sure that the Isolated Property of the EasyUAClient component you are using is set to true (if it is not, you will get an error later).
  2. When creating the UAEndpointDescriptor object specifying the server to connect to, set its UserIdentity.AliasName Property to some non-empty alias name.
  3. In the alias repository available from the AliasingManagement.Instance.AliasRepository Property, set the initial user identity by calling the SetAlias Method.
  4. Perform OPC UA operations, specifying the aliased endpoint descriptor you created earlier.
  5. When you need to switch the user, call the SetAlias Method on the alias repository again, now with the new user identity.

Example

.NET

// This example shows how to change the user identity (so-called "user switching") while keeping the same connection (OPC
// UA session).
//
// Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
// OPC client and subscriber examples in C# on GitHub: https://github.com/OPCLabs/Examples-QuickOPC-CSharp .
// Missing some example? Ask us for it on our Online Forums, https://www.opclabs.com/forum/index ! You do not have to own
// a commercial license in order to use Online Forums, and we reply to every post.

using System;
using OpcLabs.BaseLib.Aliasing;
using OpcLabs.BaseLib.Aliasing.Extensions;
using OpcLabs.BaseLib.IdentityModel.User;
using OpcLabs.EasyOpc.UA;
using OpcLabs.EasyOpc.UA.OperationModel;
using OpcLabs.EasyOpc.UA.AddressSpace.Standard;
using OpcLabs.EasyOpc.UA.Engine;

namespace UADocExamples.Users
{
    class IdentityChange
    {
        public static void Main1()
        {
            // Note that this example demonstrates the ability to dynamically change the user identity while keeping the
            // same connection. If you want a single user identity, or even multiple user identities at the same time or
            // sequentially without the need to keep the same connection, this example is not for you. In such cases, you can
            // simply specify the user identity directly in the endpoint descriptor, without the use of aliases.


            // This example is designed to work with Unified Automation UaServerNET.exe, which is a demo server from their
            // UA .NET SDK.
            UAEndpointDescriptor endpointDescriptor = "opc.tcp://localhost:48030/";

            // Require a fully secured connection. Prevents passwords from being transferred in clear text.
            endpointDescriptor.EndpointSelectionPolicy = UAEndpointSelectionPolicy.FullySecured;

            // For identity changes, the user identity in the endpoint descriptor must be specified by an alias. The name of
            // the alias (here, "CurrentUser") is up to you.
            endpointDescriptor.UserIdentity.AliasName = "CurrentUser";

            // Set the initial value of the "CurrentUser" alias to an anonymous identity.
            IAliasRepository aliasRepository = AliasingManagement.Instance.AliasRepository;
            aliasRepository.SetAlias("CurrentUser", UserIdentity.CreateAnonymousIdentity());

            // Instantiate the client object.
            var client = new EasyUAClient();

            // Identity changes require an isolated client component, otherwise you will get an error.
            client.Isolated = true;

            // Hook events to the client object.
            client.DataChangeNotification += client_DataChangeNotification;

            Console.WriteLine("Subscribing with anonymous identity...");
            client.SubscribeDataChange(endpointDescriptor, UAVariableIds.Server_ServerStatus_CurrentTime, 1000);

            Console.WriteLine("Processing data change events for 10 seconds...");
            System.Threading.Thread.Sleep(10 * 1000);

            Console.WriteLine("Changing the user identity to 'john' (a known user)...");
            aliasRepository.SetAlias("CurrentUser", UserIdentity.CreateUserNameIdentity("john", "master"));

            Console.WriteLine("Processing data change events for 10 seconds...");
            System.Threading.Thread.Sleep(10 * 1000);

            Console.WriteLine("Attempting to change the user identity to 'unknown', a user that is not known to the server...");
            // This leads to errors in operations and notifications, because the server does not know the user.
            aliasRepository.SetAlias("CurrentUser", UserIdentity.CreateUserNameIdentity("unknown", "123"));

            Console.WriteLine("Processing data change events for 10 seconds...");
            System.Threading.Thread.Sleep(10 * 1000);

            Console.WriteLine("Changing the user identity back to 'john'...");
            // The operations and notifications will no longer give errors, because the server knows and authenticates the
            // user.
            aliasRepository.SetAlias("CurrentUser", UserIdentity.CreateUserNameIdentity("john", "master"));

            Console.WriteLine("Processing data change events for 10 seconds...");
            System.Threading.Thread.Sleep(10 * 1000);

            Console.WriteLine("Unsubscribing...");
            client.UnsubscribeAllMonitoredItems();

            Console.WriteLine("Waiting for 5 seconds...");
            System.Threading.Thread.Sleep(5 * 1000);

            Console.WriteLine("Finished.");
        }
        static void client_DataChangeNotification(object sender, EasyUADataChangeNotificationEventArgs e)
        {
            // Display value.
            if (e.Succeeded)
                Console.WriteLine($"Value: {e.AttributeData.Value}");
            else
                Console.WriteLine($"*** Failure: {e.ErrorMessageBrief}");
        }
    }
}
See Also

Examples - Client OPC UA User Authentication

Fundamentals

Reference